package opencm.cli;

import java.util.List;

import opencm.Agendamento;
import opencm.Consulta;
import opencm.ErroAgendamento;
import opencm.Especialidade;
import opencm.Main;
import opencm.Medico;
import opencm.RepositorioConsulta;
import opencm.RepositorioMedico;
import opencm.ServicoAgendamento;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class CancelarConsultas extends Acao {

	private RepositorioConsulta consultas;
	private RepositorioMedico medicos;
	private ServicoAgendamento agendador;

	public CancelarConsultas() {
		this.medicos = Main.repositorioMedico;
		this.consultas = Main.repositorioConsulta;
		this.agendador = new ServicoAgendamento();
	}

	@Override
	public void executar() {
		Medico medico = selecionarUm("Médico", medicos.pesquisar());
		LocalDate data = readData("Data");
		
		List<Consulta> consultas = this.consultas.pesquisar(medico, data);
		
		for (Consulta consulta : consultas) {
			Agendamento anterior = consulta.getAgendamento();
			if (anterior.getTipo().equals(Agendamento.Tipo.MEDICO)) {
				remarcarPorMedico(consulta, anterior.getMedico(), data.toDateTimeAtStartOfDay().plusDays(1));
			} else {
				remarcarPorEspecialidade(consulta, anterior.getMedico().getEspecialidade(), data.toDateTimeAtStartOfDay().plusDays(1));				
			}
		}
		
		out.printf("Consultas remarcadas com sucesso!%n");
		out.printf("%n");
		out.printf("Novas Datas de Consulta:%n");
		out.printf("Paciente Nova Data Contato%n");
		for (Consulta c : consultas) {
			out.printf("%s %s %s", c.getPaciente().toString(), c.getAgendamento().getInicio().toString(), c.getPaciente().getPerfil().getValorContatoPreferencial());
		}
	}

	@Override
	public String toString() {
		return "Cancelar Consultas";
	}
	
	private LocalDate readData(String prompt) {
		DateTimeFormatter fmt = DateTimeFormat.forPattern("dd/MM/yyy");
		while(true) {
			try {
				return fmt.parseDateTime(readLine(prompt, true)).toLocalDate();
			} catch (IllegalArgumentException e) {
				out.println("Data inválida.");
			}
		}	
	}
	
	private void remarcarPorMedico(Consulta consulta, Medico medico, DateTime apartirDe) {
		try {
			consulta.remarcar(this.agendador.criarAgendamento(consulta, medico, apartirDe));
		} catch (ErroAgendamento e) {
			remarcarPorMedico(consulta, medico, apartirDe.plusDays(1));
		}
	}
	
	private void remarcarPorEspecialidade(Consulta consulta, Especialidade especialidade, DateTime apartirDe) {
		try {
			consulta.remarcar(this.agendador.criarAgendamento(consulta, especialidade, apartirDe));
		} catch (ErroAgendamento e) {
			remarcarPorEspecialidade(consulta, especialidade, apartirDe.plusDays(1));
		}
	}
}
